package com.song.shop.redis;

import com.sun.org.apache.xpath.internal.operations.Bool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HyperLogLogOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.*;

/**
 * Created by IntelliJ IDEA.
 *
 * @author: Song Yinhui
 * @Date: 2018/11/27 16:21
 */
//@Controller
public class RedisDistributed {

    private static Logger logger = LoggerFactory.getLogger(RedisDistributed.class);

    //@Autowired
    private RedisTemplate redisTemplate;

    private String lockKey;
    private String lockVal = Thread.currentThread().getName() + "_" + UUID.randomUUID().toString();
    private String seconds;
    private List<String> keys ;
    private List<String> args ;
    private String status = "1";


    public RedisDistributed(RedisTemplate template, String lockKey, String seconds) {
        this.redisTemplate = template;
        this.lockKey = lockKey ;
        this.seconds = seconds ;
        this.keys = new ArrayList<>();
        this.keys.add(lockKey);
        this.args = new ArrayList<>();
        this.args.add(lockVal);
        this.args.add(seconds);
        this.args.add(status);
    }

    public Boolean lock() {
        DefaultRedisScript script = new DefaultRedisScript();
        logger.info("lock  threadName=="+lockVal);
        String lockScript = "if redis.call('SETNX',KEYS[1],ARGV[1]) == 1 then redis.call('EXPIRE', KEYS[1],tonumber(ARGV[2])) return ARGV[3] else return '0' end";
        script.setScriptText(lockScript);
        Object execute = redisTemplate.execute(script, keys, lockVal, seconds, status);
        logger.info("result is [{}]", execute);
        if (execute == null){
            return false;
        }
        if ("1".equals(execute.toString())){
            return true ;
        }
        return false;
       /*HyperLogLogOperations ops = redisTemplate.opsForHyperLogLog();
       ops.add("book", "1","2","1","3");
        Long size = ops.size("book");

        logger.info("hyper操作 [{}]",size);*/
    }


    public Boolean release(){
        logger.info("release  threadName=="+lockVal);
        Boolean flag = false ;
        String unlockScript = "if redis.call('get',KEYS[1]) == ARGV[1] then redis.call('del',KEYS[1]) return ARGV[3] else return '0' end";
        DefaultRedisScript unLock = new DefaultRedisScript();
        unLock.setScriptText(unlockScript);
        Object execute = redisTemplate.execute(unLock, keys, lockVal, seconds, status);
        if (execute == null ){
            return false ;
        }
        String s = execute.toString();
        if ("1".equals(s)){
            flag = true;
        }
        return flag;
    }

}
